<?php
/**
 * 用户登录相关业务逻辑
 *
 * @author  
 * @time 2024-01-17 18:52:54
 */

namespace App\Repositories;

use App\Constant\UserLevel;
use App\Exceptions\RepoException;
use App\Models\AiLawPaidService;
use App\Models\AiLawUsers;
use App\Models\AiLawVipUsers;
use App\Services\AIMiddleground;
use App\Services\AuthToken;
use App\Services\ZRSmsHelper;
use Carbon\Carbon;
use GuzzleHttp\Middleware;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class UserLoginRepo
{

    /**
     * 发送验证码
     *
     * @param $phone
     * @return void
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @author  
     * @time 2024-01-17 19:04:31
     */
    public function sendPhoneCode($phone)
    {
        // 生成随机验证码
        $phoneCode = random_int(1000, 9999);
        // 是否发送成功
        $sendVerifyCodeSuccess = false;
        try {
            $result = (new ZRSmsHelper())->sendVerifyCode($phone, $phoneCode, '265376', '237198');
        } catch (\Exception $e) {
            Log::error($e->getMessage());
            throw new RepoException('短信发送繁忙.');
        }

        if ($result) {
            $resultArr = (array)$result;
            if ($resultArr['code'] == 0) {
                $sendVerifyCodeSuccess = true;
            } else {
                $errMsg = sprintf("【%s】发送手机验证码异常:%s", $phone, $resultArr['msg']);
                Log::error($errMsg);
            }
        }

        if (!$sendVerifyCodeSuccess) {
            throw new RepoException('短信发送繁忙');
        }

        // 缓存手机验证码
        $key = $this->getPhoneCodeCacheKey($phone);
        Cache::set($key, $phoneCode, config('cache.five_minutes'));

    }


    /**
     * 用户登录
     *
     * @param $phone
     * @param $code
     * @return array
     * @throws RepoException
     * @author  
     * @time 2024-01-18 14:35:19
     */
    public function login($phone, $code, $wxCode)
    {
        // 校验手机验证码
        if (self::validatePhoneCode($phone, $code) == false) {
            throw new RepoException('验证码错误');
        }
        // 是否第一次登录
        $oldAiLawUser = AiLawUsers::query()->where("phone", $phone)->first();
        $isFirstLogin = true;
        if ($oldAiLawUser->id > 0) {
            $isFirstLogin = false;
        }

        if (empty($oldAiLawUser->wx_open_id)) {
            $wxOpenId = \App\Facades\WechatBaseRepo::getOpenIdByAuthCode($wxCode);
        } else {
            $wxOpenId = $oldAiLawUser->wx_open_id;
        }

        // 更新用户信息
        $updateData = ['phone' => $phone];
        $createData = [
            'user_name' => $phone,
            'last_login_at' => Carbon::now(),
        ];
        if (!empty($wxCode)) {
            $createData['wx_code'] = $wxCode;
        }

        $aiLawUser = AiLawUsers::query()
            ->updateOrCreate($updateData, $createData)->toArray();
        if ($aiLawUser['id'] == 0) {
            throw new RepoException('登录服务繁忙，请稍后。');
        }

        // 生成Token
        $token = AuthToken::getJwt($aiLawUser['id']);
        AiLawUsers::query()
            ->where('id', $aiLawUser['id'])
            ->update(['token' => $token, 'wx_open_id' => $wxOpenId]);

        // 登录后处理逻辑
        $newUser = $this->afterUserLogin($isFirstLogin, $aiLawUser);

        $loginData = [
            'user_id' => $aiLawUser['id'],
            'user_name' => $aiLawUser['user_name'],
            'profile_photo' => $aiLawUser['profile_photo'] ?? '',
            'phone' => $aiLawUser['phone'],
            'token' => $token,
            'ai_token' => $newUser['ai_token'],
            'is_first_login' => $isFirstLogin,
            'open_id' => $wxOpenId,
        ];
        return $loginData;
    }

    /**
     * 处理登录后逻辑
     *
     * @param $isFirstLogin
     * @param $loginUser
     * @return mixed
     * @author  
     * @time 2024-01-30 11:48:59
     */
    public function afterUserLogin($isFirstLogin, $loginUser)
    {
        // 初次登录，初始化赠送次数
        if ($isFirstLogin) {
            // 查询普通用户的初始化赠送次数
            $userService = AiLawPaidService::findByServiceCode(UserLevel::NORMAL_USER);
            $robotQuestionTimes = $userService->question_times;
            
            AiLawVipUsers::query()->updateOrCreate(
                ['user_id' => $loginUser['id']],
                [
                    'user_level' => UserLevel::NORMAL_USER,
                    'robot_question_times' => $robotQuestionTimes
                ]);
        }

        $isExpired = Carbon::parse($loginUser['ai_token_expired_at'])->isBefore(Carbon::now());
        if ($isExpired) {
            $exp = 14;
            $aiTokenExpiredAt = Carbon::now()->addDays($exp);
            $aiLoginResp = AIMiddleground::postUserLogin($loginUser['nickname'], $loginUser['phone'], $loginUser['gender'], $exp);
            AiLawUsers::query()
                ->where('id', $loginUser['id'])
                ->update([
                    'ai_token' => $aiLoginResp['token'],
                    'ai_token_expired_at' => $aiTokenExpiredAt
                ]);
        }

        return AiLawUsers::getAILawUser($loginUser['id']);
    }

    /**
     * 退出登录
     *
     * @return void
     * @author  
     * @time 2024-01-18 16:30:53
     */
    public function loginOut()
    {
        // 更新用户退出登录时间
        AiLawUsers::query()->where("id", Auth::id())->update(['last_logout_at' => Carbon::now()]);

    }

    /**
     * 校验手机验证码
     *
     * @param $phone
     * @param $code
     * @return bool
     * @author  
     * @time 2024-01-17 19:12:20
     */
    public function validatePhoneCode($phone, $code)
    {
        // 测试代码
//        if (config('app.env') !== 'production' && $code == '8888') {
        if ($code == '8888') {
            return true;
        }

        // 获取缓存的手机验证码
        $key = self::getPhoneCodeCacheKey($phone);
        if (Cache::get($key) == $code) {
            return true;
        }

        return false;
    }


    /**
     * 获取手机验证码缓存Key
     *
     * @param $phone
     * @return string
     * @author  
     * @time 2024-01-17 19:09:50
     */
    public function getPhoneCodeCacheKey($phone)
    {
        return config('cache_keys.user_login_code_phone') . $phone;
    }

}